home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fs / fsSocketStubs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  40.1 KB  |  1,518 lines

  1. /* 
  2.  * socket.c --
  3.  *
  4.  *    Unix-compatibility routines to emulate 4.3 BSD socket-related
  5.  *    system calls for IPC using the Internet protocol suite. The
  6.  *    routines make calls to the Sprite Internet Server using Sprite
  7.  *    system calls.
  8.  *
  9.  *    Note: there is some redundance with ioctl routines (IOControl, etc.)
  10.  *    Some of these routines can be merged into the others.
  11.  *
  12.  * Copyright 1991 Regents of the University of California
  13.  * All rights reserved.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fs/fsSocketStubs.c,v 1.8 92/06/15 22:24:29 jhh Exp $ SPRITE (Berkeley)";
  18. #endif
  19.  
  20. #define MACH_UNIX_COMPAT
  21.  
  22. #include <sprite.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <user/bit.h>
  26. #include <user/dev/net.h>
  27. #include <user/fs.h>
  28. #include <user/inet.h>
  29. #include <user/status.h>
  30. #include <user/stdlib.h>
  31. #include <user/sys.h>
  32. #include <user/sys/types.h>
  33. #include <user/sys/file.h>
  34. #include <user/sys/uio.h>
  35. #include <user/errno.h>
  36. #include <mach.h>
  37. #include <fsUnixStubs.h>
  38. #include <vm.h>
  39. #include <proc.h>
  40. #include <fs.h>
  41. #include <fsio.h>
  42. #include <fsutil.h>
  43. #include <compatInt.h>
  44. #include <sys.h>
  45.  
  46. extern Mach_State    *machCurStatePtr;
  47.  
  48. static ReturnStatus IOControlStub _ARGS_ ((int streamID, int command,
  49.     int inBufSize, Address inBuffer, int outBufSize, Address outBuffer));
  50.  
  51. static char *errs[] = {"ENOERR", "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO",
  52.         "ENXIO", "E2BIG", "ENOEXEC", "EBADF", "ECHILD", "EAGAIN", "ENOMEM",
  53.         "EACCES", "EFAULT", "ENOTBLK", "EBUSY", "EEXIST", "EXDEV", "ENODEV",
  54.         "ENOTDIR", "EISDIR", "EINVAL", "ENFILE", "EMFILE", "ENOTTY",
  55.         "ETXTBSY", "EFBIG", "ENOSPC", "ESPIPE", "EROFS", "EMLINK", "EPIPE",
  56.         "EDOM", "ERANGE", "EWOULDBLOCK", "EINPROGRESS", "EALREADY", "ENOTSOCK",
  57.         "EDESTADDRREQ", "EMSGSIZE", "EPROTOTYPE", "ENOPROTOOPT",
  58.         "EPROTONOSUPPORT", "ESOCKTNOSUPPORT", "EOPNOTSUPP", "EPFNOSUPPORT",
  59.         "EAFNOSUPPORT", "EADDRINUSE", "EADDRNOTAVAIL", "ENETDOWN",
  60.         "ENETUNREACH", "ENETRESET", "ECONNABORTED", "ECONNRESET", "ENOBUFS",
  61.         "EISCONN", "ENOTCONN", "ESHUTDOWN", "ETIMEDOUT", "ECONNREFUSED",
  62.         "ELOOP", "ENAMETOOLONG", "EHOSTDOWN", "EHOSTUNREACH", "ENOTEMPTY",
  63.         "EPROCLIM", "EUSERS", "EDQUOT", "ESTALE", "EREMOTE"};
  64.  
  65. #undef Mach_SetErrno
  66. #define Mach_SetErrno(err) if (debugFsStubs) { \
  67.         printf("Error %d (%s) at %d in %s\n", err,\
  68.         err<sizeof(errs)/sizeof(char *)?errs[err]:"",\
  69.         __LINE__, __FILE__); } Proc_GetActualProc()->unixErrno = (err)
  70.  
  71. #if 1
  72. #define    DebugMsg(status, string) if (debugFsStubs) \
  73.     printf("%x: %s\n", status, string)
  74. #else
  75. #define    DebugMsg(status, string)    ;
  76. #endif
  77.  
  78. static char streamDevice[276]; /* Max host name + extra format */
  79. static char dgramDevice[276];
  80. static char rawDevice[276];
  81. static Boolean gotHostName = FALSE;
  82.  
  83. extern int debugFsStubs;
  84.  
  85.  
  86. /*
  87.  *----------------------------------------------------------------------
  88.  *
  89.  * accept --
  90.  *
  91.  *    Accept a stream connection request. This call will create a new
  92.  *    connection to the Inet server upon notification that a remote
  93.  *    connection request is pending.
  94.  *
  95.  *    If the socket is non-blocking and no remote connection requests are
  96.  *    pending, EWOULDBLOCK is returned. If the socket is blockable,
  97.  *    this routine will wait until a remote connection request arrives.
  98.  *
  99.  * Results:
  100.  *    If > 0, the stream ID of the new connection.
  101.  *    If UNIX_ERROR, errno = 
  102.  *    EINVAL        - Bad size for *namePtr.
  103.  *    EWOULDBLOCK    - Non pending requests.
  104.  *
  105.  * Side effects:
  106.  *    A new stream is created.
  107.  *
  108.  *----------------------------------------------------------------------
  109.  */
  110. #define UNIXRETURN(status) if (status==SUCCESS) { return 0; } else {\
  111.         Mach_SetErrno(Compat_MapCode(status)); return -1; }
  112.  
  113. int
  114. Fs_AcceptStub(socketID, addrPtr, addrLenPtr)
  115.     int            socketID;    /* Socket to listen on. */
  116.     struct sockaddr_in    *addrPtr;    /* Address of newly-accepted 
  117.                      * connection. (out) */
  118.     int            *addrLenPtr;    /* Size of *addrPtr. (in/out) */
  119. {
  120.     ReturnStatus    status;
  121.     int            newSocket;
  122.     int            addrLen;
  123.  
  124.     Address        usp;
  125.     ClientData        *acceptTokenPtr;
  126.     struct sockaddr_in    addr;
  127.     Fs_Stream        *streamPtr;
  128.  
  129.     usp = (Address)Mach_UserStack();
  130.     acceptTokenPtr = (ClientData *) (usp - sizeof(ClientData));
  131.  
  132.     if (addrLenPtr == (int *) NULL) {
  133.     addrLen = 0;
  134.     addrPtr = (struct sockaddr_in *) NULL;
  135.     } else {
  136.     /*
  137.      * We deal with just Internet sockets.
  138.      */
  139.     status = Vm_CopyIn(sizeof(addrLen), (Address)addrLenPtr, 
  140.                (Address)&addrLen);
  141.     if (status != SUCCESS) {
  142.         UNIXRETURN(status);
  143.     }
  144.     if (addrLen < sizeof(struct sockaddr_in)) {
  145.         UNIXRETURN(SYS_INVALID_ARG);
  146.     }
  147.     }
  148.  
  149.  
  150.     /*
  151.      * Tell the Inet server to accept connections on the socket.  If a
  152.      * connection is made, a token is returned that is used to convert the
  153.      * connection into a new socket.  If no connections are currently
  154.      * available and the socket is non-blocking, FS_WOULD_BLOCK is
  155.      * returned. If the socket is blockable, the ioctl returns
  156.      * NET_NO_CONNECTS so and Wait() must be used to wait for a
  157.      * connection.
  158.      */
  159.  
  160.     status = Fs_IOControlStub(socketID, IOC_NET_ACCEPT_CONN_1, 
  161.                 0, (Address) NULL, 
  162.             sizeof(ClientData), (Address) acceptTokenPtr);
  163.  
  164.     switch (status) {
  165.     case SUCCESS:
  166.         break;
  167.  
  168.     case FS_WOULD_BLOCK:
  169.         UNIXRETURN(FS_WOULD_BLOCK);
  170.  
  171.         case NET_NO_CONNECTS:
  172.         /*
  173.          * Wait for the server to tell us that a request has arrived.
  174.          */
  175.         (void) Wait(socketID, TRUE, (Time *) NULL);
  176.  
  177.         /*
  178.          * There's a pending connection so retry the ioctl.
  179.          */
  180.         status = Fs_IOControlStub(socketID, IOC_NET_ACCEPT_CONN_1, 
  181.                 0, (Address) NULL, 
  182.             sizeof(ClientData), (Address) acceptTokenPtr);
  183.         if (status != SUCCESS) {
  184.         DebugMsg(status, "accept (ioctl 1b)");
  185.         UNIXRETURN(status);
  186.         }
  187.         break;
  188.  
  189.     default:
  190.         DebugMsg(status, "accept (ioctl 1a)");
  191.         UNIXRETURN(status);
  192.     } 
  193.  
  194.  
  195.     /*
  196.      * Create the new socket. This socket will be converted into the new
  197.      * connection.
  198.      */
  199.  
  200.     status = Fs_Open(streamDevice, FS_READ|FS_WRITE|FS_USER|FS_FOLLOW,
  201.         FS_FILE, 0666, &streamPtr);
  202.     if (status != SUCCESS) {
  203.     DebugMsg(status, "accept (open)");
  204.     UNIXRETURN(status);
  205.     }
  206.     status = Fs_GetStreamID(streamPtr, &newSocket);
  207.     if (status != SUCCESS) {
  208.     DebugMsg(status, "accept (streamID)");
  209.     UNIXRETURN(status);
  210.     }
  211.  
  212.  
  213.     /*
  214.      * Make the new socket have the same characteristics as the
  215.      * connection socket. Also, find out who we are connected to.
  216.      */
  217.     status = Fs_IOControlStub(newSocket, IOC_NET_ACCEPT_CONN_2, 
  218.             sizeof(ClientData), (Address) acceptTokenPtr, 
  219.             addrLen, (Address) addrPtr);
  220.  
  221.     if (status != SUCCESS) {
  222.     DebugMsg(status, "accept (ioctl 2)");
  223.     UNIXRETURN(status);
  224.     }
  225.     if (addrLen > 0) {
  226.     (void)Vm_CopyIn(addrLen, (Address)addrPtr, (Address)&addr);
  227.     addr.sin_family = AF_INET;
  228.     (void)Vm_CopyOut(addrLen, (Address)&addr, (Address)addrPtr);
  229.     }
  230.     return newSocket;
  231. }
  232. /*
  233.  *----------------------------------------------------------------------
  234.  *
  235.  * Fs_BindStub --
  236.  *
  237.  *    Assigns a local <address,port> tuple to a socket that does 
  238.  *    not have one.
  239.  *
  240.  * Results:
  241.  *    If 0        - Successful.
  242.  *    If UNIX_ERROR, then errno = 
  243.  *    EINVAL        - Bad size for *namePtr, already bound to an address.
  244.  *    EADDRINUSE    - The address is already in use.
  245.  *    EADDRNOTAVAIL    - The address is not valid for this host.
  246.  *
  247.  * Side effects:
  248.  *    The socket local address is set.
  249.  *
  250.  *----------------------------------------------------------------------
  251.  */
  252.  
  253. int 
  254. Fs_BindStub(socketID, namePtr, nameLen)
  255.     int            socketID;    /* Stream ID of unnamed socket. */
  256.     struct sockaddr    *namePtr;    /* Local address,port for this socket.*/
  257.     int            nameLen;    /* Size of *namePtr. */
  258. {
  259.     ReturnStatus    status;
  260.     Proc_ControlBlock *procPtr;
  261.     Fs_Stream      *streamPtr;
  262.     Fs_IOCParam ioctl;
  263.     Fs_IOReply reply;
  264.  
  265.     if (debugFsStubs) {
  266.     printf("Fs_BindStub(%d, %x, %d)\n", socketID, namePtr, nameLen);
  267.     }
  268.     if (nameLen != sizeof(struct sockaddr_in)) {
  269.     Mach_SetErrno(EINVAL);
  270.     return -1;
  271.     }
  272.  
  273.     procPtr = Proc_GetEffectiveProc();
  274.     status = Fs_GetStreamPtr(procPtr, socketID, &streamPtr);
  275.     if (status != SUCCESS) {
  276.     Mach_SetErrno(Compat_MapCode(status));
  277.     return -1;
  278.     }
  279.     if (!Fsutil_HandleValid(streamPtr->ioHandlePtr)) {
  280.     /* FS_STALE_HANDLE */
  281.     Mach_SetErrno(EINVAL);
  282.     return -1;
  283.     }
  284.     ioctl.command = IOC_NET_SET_LOCAL_ADDR;
  285.     ioctl.format = mach_Format;
  286.     ioctl.procID = procPtr->processID;
  287.     ioctl.familyID = procPtr->familyID;
  288.     ioctl.uid = procPtr->effectiveUserID;
  289.     ioctl.outBufSize = 0;
  290.     ioctl.outBuffer = NULL;
  291.     if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM) {
  292.     ioctl.inBufSize = nameLen;
  293.     ioctl.inBuffer = (Address)namePtr;
  294.     ioctl.flags = FS_USER_IN|FS_USER_OUT;
  295.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  296.     if (status != SUCCESS) {
  297.         Mach_SetErrno(Compat_MapCode(status));
  298.         return -1;
  299.     }
  300.     return 0;
  301.     }
  302.     ioctl.inBuffer = malloc(nameLen);
  303.     status = Vm_CopyIn(nameLen, (Address)namePtr, ioctl.inBuffer);
  304.     if (status != SUCCESS) {
  305.     free(ioctl.inBuffer);
  306.     Mach_SetErrno(EFAULT);
  307.     return -1;
  308.     }
  309.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  310.     free(ioctl.inBuffer);
  311.     if (status != SUCCESS) {
  312.     Mach_SetErrno(Compat_MapCode(status));
  313.     return -1;
  314.     }
  315.     return 0;
  316. }
  317.  
  318.  
  319. /*
  320.  *----------------------------------------------------------------------
  321.  *
  322.  * getpeername --
  323.  *
  324.  *    Find out the remote address that this socket is connected to.
  325.  *
  326.  * Results:
  327.  *    If 0        - Successful.
  328.  *    If UNIX_ERROR, then errno = 
  329.  *    EINVAL        - Bad size for *namePtr.
  330.  *    ENOTCONN    - The socket is not connected.
  331.  *    EFAULT        - Invalid argument to the ioctl.
  332.  *
  333.  * Side effects:
  334.  *    None.
  335.  *
  336.  *----------------------------------------------------------------------
  337.  */
  338.  
  339. int
  340. Fs_GetpeernameStub(socketID, namePtr, nameLenPtr)
  341.     int            socketID;    /* Stream ID of socket connected to 
  342.                      * remote peer. */
  343.     struct sockaddr    *namePtr;    /* Upon return, <addr,port> for 
  344.                      * remote peer. */
  345.     int            *nameLenPtr;    /* Size of *namePtr. (in/out) */
  346. {
  347.     ReturnStatus    status;
  348.     int            nameLen;
  349.  
  350.     if (debugFsStubs) {
  351.     printf("Fs_GetpeernameStub(%d, %x, %x)\n", socketID, namePtr,
  352.         nameLenPtr);
  353.     }
  354.     if (nameLenPtr == (int *) NULL) {
  355.     Mach_SetErrno(EINVAL);
  356.     return -1;
  357.     }
  358.     status = Vm_CopyIn(sizeof(int), (Address)nameLenPtr, (Address)&nameLen);
  359.     if (status != SUCCESS) {
  360.     Mach_SetErrno(Compat_MapCode(status));
  361.     return -1;
  362.     }
  363.     if (nameLen < sizeof(struct sockaddr_in)) {
  364.     Mach_SetErrno(EINVAL);
  365.     return -1;
  366.     }
  367.     if (nameLen > sizeof(struct sockaddr_in)) {
  368.     nameLen = sizeof(struct sockaddr_in);
  369.     status = Vm_CopyOut(sizeof(int),(Address)&nameLen, (Address)nameLenPtr);
  370.     if (status != SUCCESS) {
  371.         Mach_SetErrno(Compat_MapCode(status));
  372.         return -1;
  373.     }
  374.     }
  375.     status = Fs_IOControlStub(socketID, IOC_NET_GET_REMOTE_ADDR, 
  376.             0, (Address) NULL, 
  377.             nameLen, (Address) namePtr);
  378.     if (status != SUCCESS) {
  379.     DebugMsg(status, "getpeername");
  380.     Mach_SetErrno(Compat_MapCode(status));
  381.     return -1;
  382.     }
  383.     return 0;
  384. }
  385.  
  386.  
  387. /*
  388.  *----------------------------------------------------------------------
  389.  *
  390.  * getsockname --
  391.  *
  392.  *    Find out the local address for this socket, which was
  393.  *    set with the bind routine or by the connect routine.
  394.  *
  395.  * Results:
  396.  *    If 0        - Successful.
  397.  *    If UNIX_ERROR, then errno = 
  398.  *    EINVAL        - Bad size for *namePtr.
  399.  *    EFAULT        - Invalid argument to the ioctl.
  400.  *
  401.  * Side effects:
  402.  *    None.
  403.  *
  404.  *----------------------------------------------------------------------
  405.  */
  406.  
  407. int
  408. Fs_GetsocknameStub(socketID, namePtr, nameLenPtr)
  409.     int            socketID;    /* Stream ID of socket to get name of.*/
  410.     struct sockaddr    *namePtr;    /* Upon return, current <addr,port> for
  411.                      * this socket. */
  412.     int            *nameLenPtr;    /* Size of *namePtr. (in/out) */
  413. {
  414.     ReturnStatus    status;
  415.     int            nameLen;
  416.  
  417.     if (debugFsStubs) {
  418.     printf("Fs_GetsocknameStub(%d, %x, %x)\n", socketID, namePtr,
  419.         nameLenPtr);
  420.     }
  421.     if (nameLenPtr == (int *) NULL) {
  422.     Mach_SetErrno(EINVAL);
  423.     return -1;
  424.     }
  425.     status = Vm_CopyIn(sizeof(int), (Address)nameLenPtr, (Address)&nameLen);
  426.     if (status != SUCCESS) {
  427.     Mach_SetErrno(Compat_MapCode(status));
  428.     return -1;
  429.     }
  430.     if (nameLen < sizeof(struct sockaddr_in)) {
  431.     Mach_SetErrno(EINVAL);
  432.     return -1;
  433.     }
  434.     if (nameLen > sizeof(struct sockaddr_in)) {
  435.     nameLen = sizeof(struct sockaddr_in);
  436.     status = Vm_CopyOut(sizeof(int),(Address)&nameLen, (Address)nameLenPtr);
  437.     if (status != SUCCESS) {
  438.         Mach_SetErrno(Compat_MapCode(status));
  439.         return -1;
  440.     }
  441.     }
  442.  
  443.     status = Fs_IOControlStub(socketID, IOC_NET_GET_LOCAL_ADDR, 
  444.                   0, (Address) NULL, 
  445.                   nameLen, (Address) namePtr);
  446.  
  447.     if (status != SUCCESS) {
  448.     DebugMsg(status, "getsockname");
  449.     Mach_SetErrno(Compat_MapCode(status));
  450.     return -1;
  451.     }
  452.     return 0;
  453. }
  454.  
  455. /*
  456.  *----------------------------------------------------------------------
  457.  *
  458.  * getsockopt --
  459.  *
  460.  *    Get the value for a socket option.
  461.  *
  462.  * Results:
  463.  *    If 0        - Successful.
  464.  *    If UNIX_ERROR, then errno = 
  465.  *    EFAULT        - Invalid argument to the ioctl.
  466.  *
  467.  * Side effects:
  468.  *    None.
  469.  *
  470.  *----------------------------------------------------------------------
  471.  */
  472. int
  473. Fs_GetsockoptStub(socketID, level, optName, optVal, optLenPtr)
  474.     int        socketID;    /* Stream ID of socket to get options on. */
  475.     int        level;        /* Socket or protocol level to get the option.*/
  476.     int        optName;    /* Type of option to get. */
  477.     char    *optVal;    /* Address of buffer to store the result. */
  478.     int        *optLenPtr;    /* In: Size of *optVal, out: # of bytes stored
  479.                  * in *optVal. */
  480. {
  481.     ReturnStatus    status;
  482.     int            optionsArray[2];
  483.     int            optLen;
  484.     Address             tmp;
  485.  
  486.     if (debugFsStubs) {
  487.     printf("Fs_GetsockoptStub(%d, %d, %d, %x, %x)\n", socketID,
  488.         level, optName, optVal, optLenPtr);
  489.     }
  490.  
  491.     /*
  492.      * OptionsArray is used to give the server the values of "level"
  493.      * and "optName". A buffer ("newBufPtr") is needed to get the option
  494.      * value and the length of the value.
  495.      */
  496.     optionsArray[0] = level;
  497.     optionsArray[1] = optName;
  498.  
  499.     status = Vm_CopyIn(sizeof(int), (Address)optLenPtr, (Address)&optLen);
  500.     if (status != SUCCESS) {
  501.     return(status);
  502.     }
  503.     tmp = malloc(optLen);
  504.     status = IOControlStub(socketID, IOC_NET_GET_OPTION,
  505.             sizeof(optionsArray), (Address) optionsArray, 
  506.             optLen, tmp);
  507.  
  508.     if (status != SUCCESS) {
  509.     printf("getsockopt: option %d returned status %d\n", optName, status);
  510.     Mach_SetErrno(Compat_MapCode(status));
  511.     return -1;
  512.     }
  513.     if (optName == SO_ERROR) {
  514.     /*
  515.      * The error value is a Sprite ReturnStatus so we must convert it
  516.      * to the equivalent Unix value.
  517.      */
  518.     * (int *) tmp = Compat_MapCode(* (int *) tmp);
  519.     }
  520.     status = Vm_CopyOut(optLen, tmp, optVal);
  521.     if (status != SUCCESS) {
  522.     Mach_SetErrno(Compat_MapCode(status));
  523.     return -1;
  524.     }
  525.     return 0;
  526. }
  527.  
  528. /*
  529.  *----------------------------------------------------------------------
  530.  *
  531.  * setsockopt --
  532.  *
  533.  *    Set the value for a socket option.
  534.  *
  535.  * Results:
  536.  *    If 0        - Successful.
  537.  *    If UNIX_ERROR, then errno = 
  538.  *    EFAULT        - Invalid argument to the ioctl.
  539.  *
  540.  * Side effects:
  541.  *    None.
  542.  *
  543.  *----------------------------------------------------------------------
  544.  */
  545.  
  546. /*VARARGS*/
  547. int
  548. Fs_SetsockoptStub(socketID, level, optName, optVal, optLen)
  549.     int        socketID;    /* Stream ID of socket to set options on. */
  550.     int        level;        /* Socket or protocol level to get the option.*/
  551.     int        optName;    /* Type of option to get. */
  552.     char    *optVal;    /* Address of buffer to store the result. */
  553.     int        optLen;        /* Size of *optVal. */
  554. {
  555.     ReturnStatus    status;
  556.     int            *kernBufPtr;
  557.  
  558.     if (debugFsStubs) {
  559.     printf("Fs_SetsockoptStub(%d, %d, %d, %x, %d)\n", socketID,
  560.         level, optName, optVal, optLen);
  561.     }
  562.     kernBufPtr = (int *)malloc(2 * sizeof(int) + optLen);
  563.     kernBufPtr[0] = level;
  564.     kernBufPtr[1] = optName;
  565.     status = Vm_CopyIn(optLen, (Address)optVal, (Address)&kernBufPtr[2]);
  566.     if (status != SUCCESS) {
  567.     free((Address)kernBufPtr);
  568.     Mach_SetErrno(Compat_MapCode(status));
  569.     return -1;
  570.     }
  571.     status = IOControlStub(socketID, IOC_NET_SET_OPTION,
  572.                   2 * sizeof(int) + optLen, (Address)kernBufPtr,
  573.                   0, (Address) NULL);
  574.     free((Address)kernBufPtr);
  575.     if (status != SUCCESS) {
  576.     DebugMsg(status, "getsockopt");
  577.     Mach_SetErrno(Compat_MapCode(status));
  578.     return -1;
  579.     }
  580.     return 0;
  581. }
  582.  
  583. /*
  584.  *----------------------------------------------------------------------
  585.  *
  586.  * listen --
  587.  *
  588.  *    Allows a stream socket to accept remote connection requests and to
  589.  *    specify how many such requests will be queued up before they 
  590.  *    are refused.
  591.  *
  592.  * Results:
  593.  *    If 0        - Successful.
  594.  *    If UNIX_ERROR, then errno = 
  595.  *    EOPNOTSUPP    - The socket type doesn't allow a listen operation.
  596.  *    EFAULT        - Invalid argument to the ioctl.
  597.  *
  598.  * Side effects:
  599.  *    None.
  600.  *
  601.  *----------------------------------------------------------------------
  602.  */
  603.  
  604. ReturnStatus
  605. Fs_ListenStub(socketID, backlog)
  606.     int    socketID;    /* Stream ID of socket to be put in listen mode. */
  607.     int    backlog;    /* How many connection requests to queue. */
  608. {
  609.     ReturnStatus    status;
  610.  
  611.     if (debugFsStubs) {
  612.     printf("Fs_ListenStub(%d, %d)\n", socketID, backlog);
  613.     }
  614.     status = IOControlStub(socketID, IOC_NET_LISTEN,
  615.             sizeof(backlog), (Address) &backlog,
  616.             0, (Address) NULL);
  617.     if (status != SUCCESS) {
  618.     DebugMsg(status, "listen");
  619.     Mach_SetErrno(Compat_MapCode(status));
  620.     return -1;
  621.     }
  622.     return 0;
  623. }
  624.  
  625. /*
  626.  *----------------------------------------------------------------------
  627.  *
  628.  * recv --
  629.  *
  630.  *    Read data from a connected socket. 
  631.  *
  632.  * Results:
  633.  *    See recvfrom().
  634.  *
  635.  * Side effects:
  636.  *    None.
  637.  *
  638.  *----------------------------------------------------------------------
  639.  */
  640.  
  641. int
  642. Fs_RecvStub(socketID, bufPtr, bufSize, flags)
  643.     int        socketID;
  644.     char    *bufPtr;    /* Address of buffer to place the data in. */
  645.     int        bufSize;    /* Size of *bufPtr. */
  646.     int        flags;        /* Type of operatrion: OR of MSG_OOB, MSG_PEEK*/
  647. {
  648.     if (debugFsStubs) {
  649.     printf("Fs_RecvStub(%d, %x, %d, %d)\n", socketID, bufPtr, bufSize,
  650.         flags);
  651.     }
  652.     return Fs_RecvfromStub(socketID, bufPtr, bufSize, flags, 
  653.                 (struct sockaddr *) NULL, (int *) NULL);
  654. }
  655.  
  656. /*
  657.  *----------------------------------------------------------------------
  658.  *
  659.  * recvfrom --
  660.  *
  661.  *    Read data from a socket.
  662.  *
  663.  * Results:
  664.  *    If 0        - Successful.
  665.  *    If UNIX_ERROR, then errno = 
  666.  *    EINVAL        - Bad size or address for senderPtr, senderLenPtr.
  667.  *    EWOULDBLOCK    - If non-blocking, no data are available.
  668.  *    EFAULT        - Invalid argument to the ioctl.
  669.  *
  670.  * Side effects:
  671.  *    None.
  672.  *
  673.  *----------------------------------------------------------------------
  674.  */
  675.  
  676. int
  677. Fs_RecvfromStub(socketID, bufPtr, bufSize, flags, senderPtr, 
  678.          senderLenPtr)
  679.     int            socketID;    /* Socket to read. */
  680.     char        *bufPtr;    /* Buffer to place the data in. */
  681.     int            bufSize;    /* Size of *bufPtr. */
  682.     int            flags;        /* Type of operatrion: OR of 
  683.                      *  MSG_OOB, MSG_PEEK*/
  684.     struct sockaddr    *senderPtr;    /* Address of sender of the data. */
  685.     int            *senderLenPtr;    /* Size of *senderPtr. (in/out) */
  686. {
  687.     ReturnStatus    status;
  688.     int            *intPtr;
  689.     int            senderLen;
  690.     int            value;
  691.  
  692.     if (debugFsStubs) {
  693.     printf("Fs_RecvfromStub(%d, %x, %d, %d, %x, %x)\n",
  694.         socketID, bufPtr, bufSize, flags, senderPtr, senderLenPtr);
  695.     }
  696.     intPtr = (int *)(Mach_UserStack() - sizeof(int));
  697.     if (senderPtr != (struct sockaddr *) NULL) {
  698.     if (senderLenPtr == (int *) NULL) {
  699.         return(SYS_INVALID_ARG);
  700.     }
  701.     status = Vm_CopyIn(sizeof(int), (Address)senderLenPtr,
  702.                (Address)&senderLen);
  703.     if (status != SUCCESS) {
  704.         return(status);
  705.     }
  706.     if (senderLen != sizeof(struct sockaddr_in)) {
  707.         Mach_SetErrno(EINVAL);
  708.         return -1;
  709.     }
  710.     }
  711.  
  712.     /*
  713.      * If there are flags, ship them to the server.
  714.      */
  715.     if (flags != 0) {
  716.     status = Vm_CopyOut(sizeof(flags), (Address)&flags, (Address)intPtr);
  717.     if (status != SUCCESS) {
  718.         return(status);
  719.     }
  720.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FLAGS,
  721.                   sizeof(flags), (Address)intPtr,
  722.                   0, (Address) NULL);
  723.     if (status != SUCCESS) {
  724.         DebugMsg(status, "recvfrom (ioctl recv_flags)");
  725.         Mach_SetErrno(Compat_MapCode(status));
  726.         return -1;
  727.     }
  728.     }
  729.  
  730.     status = Fs_ReadStub(socketID, bufSize, bufPtr, intPtr);
  731.     if (status != SUCCESS) {
  732.     DebugMsg(status, "recvfrom (read)");
  733.     Mach_SetErrno(Compat_MapCode(status));
  734.     return -1;
  735.     }
  736.     (void)Vm_CopyIn(sizeof(int), (Address)intPtr, (Address) &value);
  737.  
  738.     /*
  739.      * If the caller wants the address of the sender, ask the server for it.
  740.      */
  741.     if (senderPtr != (struct sockaddr *) NULL) {
  742.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FROM,
  743.                   0, (Address) NULL,
  744.                   senderLen, (Address) senderPtr);
  745.     if (status != SUCCESS) {
  746.         DebugMsg(status, "recvfrom (ioctl get_remote)");
  747.         Mach_SetErrno(Compat_MapCode(status));
  748.         return -1;
  749.     }
  750.     }
  751.     return value;
  752. }
  753.  
  754. /*
  755.  *----------------------------------------------------------------------
  756.  *
  757.  * recvmsg --
  758.  *
  759.  *    Read data from a socket using multiple buffers.
  760.  *
  761.  * Results:
  762.  *    If 0        - Successful.
  763.  *    If UNIX_ERROR, then errno = 
  764.  *    EINVAL        - Bad size or address for msg_name, msg_namelen;
  765.  *                I/O vector length too big.
  766.  *    EWOULDBLOCK    - If non-blocking, no data are available.
  767.  *    EFAULT        - Invalid argument to the ioctl, null address 
  768.  *               for msgPtr.
  769.  *
  770.  * Side effects:
  771.  *    None.
  772.  *
  773.  *----------------------------------------------------------------------
  774.  */
  775.  
  776. int
  777. Fs_RecvmsgStub(socketID, msgPtr, flags)
  778.     int            socketID;    /* Sokect to read data from. */
  779.     struct msghdr    *msgPtr;    /* I/O vector of buffers to store the
  780.                      * data. */
  781.     int            flags;        /* Type of operatrion: OR of 
  782.                      *  MSG_OOB, MSG_PEEK*/
  783. {
  784.     int            *intPtr;
  785.     ReturnStatus    status;
  786.     struct msghdr    msg;
  787.  
  788.     if (debugFsStubs) {
  789.     printf("Fs_RecvmsgStub(%d, %x, %d)\n", socketID, msgPtr, flags);
  790.     }
  791.     if (msgPtr == (struct msghdr *) NULL) {
  792.     Mach_SetErrno(EACCES);
  793.     return -1;
  794.     }
  795.     status = Vm_CopyIn(sizeof(msg), (Address)msgPtr, (Address)&msg);
  796.     if (status != SUCCESS) {
  797.     Mach_SetErrno(Compat_MapCode(status));
  798.     return -1;
  799.     }
  800.  
  801.     if (msg.msg_name != (Address) NULL) {
  802.     if (msg.msg_namelen != sizeof(struct sockaddr_in)) {
  803.         Mach_SetErrno(EINVAL);
  804.         return -1;
  805.     }
  806.     }
  807.  
  808.     if (msg.msg_iovlen > MSG_MAXIOVLEN) {
  809.         Mach_SetErrno(EINVAL);
  810.         return -1;
  811.     }
  812.  
  813.     intPtr = (int *)(Mach_UserStack() - sizeof(int));
  814.     /*
  815.      * If there are flags, ship them to the server.
  816.      */
  817.     if (flags != 0) {
  818.     status = Vm_CopyOut(sizeof(flags), (Address)&flags, (Address)intPtr);
  819.     if (status != SUCCESS) {
  820.         Mach_SetErrno(Compat_MapCode(status));
  821.         return -1;
  822.     }
  823.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FLAGS,
  824.                 sizeof(flags), (Address)intPtr,
  825.                 0, (Address) NULL);
  826.     if (status != SUCCESS) {
  827.         DebugMsg(status, "recvmsg (ioctl recv_flags)");
  828.         Mach_SetErrno(Compat_MapCode(status));
  829.         return -1;
  830.     }
  831.     }
  832.     status = Fs_ReadvStub(socketID, msg.msg_iov, msg.msg_iovlen);
  833.     if (status != SUCCESS) {
  834.     Mach_SetErrno(Compat_MapCode(status));
  835.     return -1;
  836.     }
  837.  
  838.     /*
  839.      * If the caller wants the address of the sender, ask the server for it.
  840.      */
  841.     if (msg.msg_name != (Address) NULL) {
  842.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FROM,
  843.             0, (Address) NULL,
  844.             msg.msg_namelen, (Address) msg.msg_name);
  845.     if (status != SUCCESS) {
  846.         DebugMsg(status, "recvmsg (ioctl recv_from)");
  847.         Mach_SetErrno(Compat_MapCode(status));
  848.         return -1;
  849.     }
  850.     }
  851.     return 0;
  852. }
  853.  
  854. /*
  855.  *----------------------------------------------------------------------
  856.  *
  857.  * send --
  858.  *
  859.  *    Write data to a connected socket.
  860.  *
  861.  * Results:
  862.  *    See sendto().
  863.  *
  864.  * Side effects:
  865.  *    None.
  866.  *
  867.  *----------------------------------------------------------------------
  868.  */
  869.  
  870. int
  871. Fs_SendStub(socketID, bufPtr, bufSize, flags)
  872.     int        socketID;    /* Socket to send data on. */
  873.     char    *bufPtr;    /* Address of buffer to send. */
  874.     int        bufSize;    /* Size of *bufPtr. */
  875.     int        flags;        /* Type of operatrion: OR of 
  876.                  *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  877. {
  878.  
  879.     return Fs_SendtoStub(socketID, bufPtr, bufSize, flags,
  880.                      (struct sockaddr *)NULL, 0);
  881. }
  882.  
  883. /*
  884.  *----------------------------------------------------------------------
  885.  *
  886.  * sendto --
  887.  *
  888.  *    Send a message from a socket.
  889.  *
  890.  * Results:
  891.  *    If 0        - Successful.
  892.  *    If UNIX_ERROR, then errno = 
  893.  *    EINVAL        - Bad size or address for destPtr, destLen..
  894.  *    EWOULDBLOCK    - If non-blocking, the server buffers are too
  895.  *              full to accept the data.
  896.  *    EMSGSIZE    - The buffer is too large to be sent in 1 packet.
  897.  *    EFAULT        - Invalid argument to the ioctl.
  898.  *
  899.  * Side effects:
  900.  *    None.
  901.  *
  902.  *----------------------------------------------------------------------
  903.  */
  904.  
  905. int
  906. Fs_SendtoStub(socketID, bufPtr, bufSize, flags, destPtr, destLen)
  907.     int        socketID;    /* Socket to send data on. */
  908.     char    *bufPtr;    /* Address of buffer to send. */
  909.     int        bufSize;    /* Size of *bufPtr. */
  910.     int        flags;        /* Type of operatrion: OR of 
  911.                  *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  912.     struct sockaddr    *destPtr;    /* Destination to send the data to. */
  913.     int            destLen;    /* Size of *destPtr.  */
  914. {
  915.     ReturnStatus    status;
  916.  
  917.     if (debugFsStubs) {
  918.     printf("Fs_SendtoStub(%d, %x, %d, %d)\n", socketID, bufPtr,
  919.         bufSize, flags);
  920.     }
  921.     /*
  922.      * If either the flags or a destination are given, send them to the server.
  923.      */
  924.     if ((flags != 0) || (destPtr != (struct sockaddr *) NULL)) {
  925.     Net_SendInfo    sendInfo;
  926.  
  927.     if (destPtr != (struct sockaddr *) NULL) {
  928.         if (destLen != sizeof(struct sockaddr_in)) {
  929.         Mach_SetErrno(EINVAL);
  930.         return -1;
  931.         }
  932.         sendInfo.addressValid = TRUE;
  933.         status = Vm_CopyIn(sizeof(Net_InetSocketAddr), (Address)destPtr,
  934.               (Address)&sendInfo.address.inet);
  935.         if (status != SUCCESS) {
  936.         Mach_SetErrno(EFAULT);
  937.         return -1;
  938.         }
  939.     } else {
  940.         sendInfo.addressValid = FALSE;
  941.     }
  942.     sendInfo.flags = flags;
  943.     status = IOControlStub(socketID, IOC_NET_SEND_INFO,
  944.             sizeof(sendInfo), (Address) &sendInfo,
  945.             0, (Address) NULL);
  946.     if (status != SUCCESS) {
  947.         DebugMsg(status, "sendto (ioctl)");
  948.         Mach_SetErrno(Compat_MapCode(status));
  949.         return -1;
  950.     }
  951.     }
  952.     return Fs_NewWriteStub(socketID, bufPtr, bufSize);
  953. }
  954.  
  955. /*
  956.  *----------------------------------------------------------------------
  957.  *
  958.  * sendmsg --
  959.  *
  960.  *    Send a message from a socket.
  961.  *
  962.  * Results:
  963.  *    If 0        - Successful.
  964.  *    If UNIX_ERROR, then errno = 
  965.  *    EINVAL        - Bad size or address for msg_name, msg_namelen;
  966.  *                I/O vector length too big.
  967.  *    EWOULDBLOCK    - If non-blocking, the server buffers are too full 
  968.  *              accept the data.
  969.  *    EFAULT        - Invalid argument to the ioctl, null address 
  970.  *               for msgPtr.
  971.  *
  972.  * Side effects:
  973.  *    None.
  974.  *
  975.  *----------------------------------------------------------------------
  976.  */
  977.  
  978. int
  979. Fs_SendmsgStub(socketID, msgPtr, flags)
  980.     int            socketID;    /* Socket to send data on. */
  981.     struct msghdr    *msgPtr;    /* I/O vector of buffers containing
  982.                      * data to send. */
  983.     int            flags;        /* Type of operatrion: OR of 
  984.                      *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  985. {
  986.     ReturnStatus    status;
  987.     struct msghdr    msg;
  988.  
  989.     if (debugFsStubs) {
  990.     printf("Fs_SendmsgStub(%d, %x, %d)\n", socketID, msgPtr, flags);
  991.     }
  992.  
  993.     if (msgPtr == (struct msghdr *) NULL) {
  994.     Mach_SetErrno(EACCES);
  995.     return -1;
  996.     }
  997.     status = Vm_CopyIn(sizeof(msg), (Address)msgPtr, (Address)&msg);
  998.     if (status != SUCCESS) {
  999.     Mach_SetErrno(EFAULT);
  1000.     return -1;
  1001.     }
  1002.     if (msg.msg_iovlen > MSG_MAXIOVLEN) {
  1003.     Mach_SetErrno(EINVAL);
  1004.     return -1;
  1005.     }
  1006.  
  1007.     if ((flags != 0) || (msg.msg_name != (Address) NULL)) {
  1008.     Net_SendInfo    sendInfo;
  1009.  
  1010.     if (msg.msg_name != (Address) NULL) {
  1011.         if (msg.msg_namelen != sizeof(struct sockaddr_in)) {
  1012.         Mach_SetErrno(EINVAL);
  1013.         return -1;
  1014.         }
  1015.         sendInfo.addressValid = TRUE;
  1016.         status = Vm_CopyIn(sizeof(Net_InetSocketAddr),
  1017.                    (Address)msg.msg_name,
  1018.                        (Address)&sendInfo.address.inet);
  1019.         if (status != SUCCESS) {
  1020.         Mach_SetErrno(EFAULT);
  1021.         return -1;
  1022.         }
  1023.     } else {
  1024.         sendInfo.addressValid = FALSE;
  1025.     }
  1026.     sendInfo.flags = flags;
  1027.     status = IOControlStub(socketID, IOC_NET_SEND_INFO,
  1028.                 sizeof(sendInfo), (Address) &sendInfo,
  1029.                 0, (Address) NULL);
  1030.  
  1031.     if (status != SUCCESS) {
  1032.         DebugMsg(status, "sendmsg (ioctl)");
  1033.         Mach_SetErrno(Compat_MapCode(status));
  1034.         return -1;
  1035.     }
  1036.     }
  1037.  
  1038.     return Fs_WritevStub(socketID, msg.msg_iov, msg.msg_iovlen);
  1039. }
  1040.  
  1041. /*
  1042.  *----------------------------------------------------------------------
  1043.  *
  1044.  * shutdown --
  1045.  *
  1046.  *    Shut down part of a full-duplex connection.
  1047.  *
  1048.  * Results:
  1049.  *    0        - The action was successful.
  1050.  *
  1051.  * Side effects:
  1052.  *    None.
  1053.  *
  1054.  *----------------------------------------------------------------------
  1055.  */
  1056.  
  1057. ReturnStatus
  1058. Fs_ShutdownStub(socketID, action)
  1059.     int        socketID;    /* Socket to shut down. */
  1060.     int        action;        /* 0 -> disallow further recvs, 
  1061.                  * 1 -> disallow further sends,
  1062.                  * 2 -> combination of above. */
  1063. {
  1064.     ReturnStatus    status;
  1065.  
  1066.     if (debugFsStubs) {
  1067.     printf("Fs_ShutdownStub(%d, %d)\n", socketID, action);
  1068.     }
  1069.     status = IOControlStub(socketID, IOC_NET_SHUTDOWN, 
  1070.             sizeof(action), (Address) &action,
  1071.             0, (Address) NULL);
  1072.  
  1073.     if (status != SUCCESS) {
  1074.     DebugMsg(status, "shutdown");
  1075.     Mach_SetErrno(Compat_MapCode(status));
  1076.     return -1;
  1077.     }
  1078.     return 0;
  1079. }
  1080.  
  1081. static ReturnStatus
  1082. IOControlStub(streamID, command, inBufSize, inBuffer,
  1083.                outBufSize, outBuffer)
  1084.     int     streamID;    /* User's handle on the stream */
  1085.     int     command;    /* IOControl command */
  1086.     int     inBufSize;    /* Size of inBuffer */
  1087.     Address     inBuffer;    /* Command specific input parameters */
  1088.     int     outBufSize;    /* Size of outBuffer */
  1089.     Address     outBuffer;    /* Command specific output parameters */
  1090. {
  1091.     Proc_ControlBlock *procPtr;
  1092.     Fs_ProcessState *fsPtr;
  1093.     Fs_Stream      *streamPtr;
  1094.     register ReturnStatus status = SUCCESS;
  1095.     Fs_IOCParam ioctl;
  1096.     Fs_IOReply reply;
  1097.  
  1098.     if (debugFsStubs) {
  1099.     printf("IOControlStub(%d, %x)\n", streamID, command);
  1100.     }
  1101.  
  1102.     /*
  1103.      * Get a stream pointer.
  1104.      */
  1105.     procPtr = Proc_GetEffectiveProc();
  1106.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  1107.     if (status != SUCCESS) {
  1108.     return(status);
  1109.     }
  1110.  
  1111.     if (!Fsutil_HandleValid(streamPtr->ioHandlePtr)) {
  1112.     return(FS_STALE_HANDLE);
  1113.     }
  1114.  
  1115.     ioctl.command = command;
  1116.     ioctl.format = mach_Format;
  1117.     ioctl.procID = procPtr->processID;
  1118.     ioctl.familyID = procPtr->familyID;
  1119.     ioctl.uid = procPtr->effectiveUserID;
  1120.  
  1121.     /*
  1122.      * Fast path for non-generic I/O controls to pseudo-devices.
  1123.      * We don't copy in/out the user's parameter blocks because the
  1124.      * pseudo-device code does direct cross-address-space copy later.
  1125.      * We also skip the check against large parameter blocks so arbitrary
  1126.      * amounts of data can be fed to and from a pseudo-device.
  1127.      */
  1128.     if ((streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM) &&
  1129.     (command > IOC_GENERIC_LIMIT)) {
  1130.     ioctl.inBufSize = inBufSize;
  1131.     ioctl.inBuffer = inBuffer;
  1132.     ioctl.outBufSize = outBufSize;  
  1133.     ioctl.outBuffer = outBuffer;
  1134.     ioctl.flags = FS_USER_IN|FS_USER_OUT;
  1135.     return(Fs_IOControl(streamPtr, &ioctl, &reply));
  1136.     }
  1137.  
  1138.     if (inBufSize > IOC_MAX_BYTES || outBufSize > IOC_MAX_BYTES) {
  1139.     return(SYS_INVALID_ARG);
  1140.     }
  1141.     ioctl.flags = 0;    /* We'll copy buffer's into/out of the kernel */
  1142.  
  1143.  
  1144.     if ((outBufSize > 0) && (outBuffer != (Address)0) &&
  1145.                 (outBuffer != (Address)NIL)){
  1146.     ioctl.outBuffer = outBuffer;
  1147.     ioctl.outBufSize = outBufSize;
  1148.     } else {
  1149.     ioctl.outBuffer = (Address)NIL;
  1150.     ioctl.outBufSize = outBufSize = 0;
  1151.     }
  1152.     if ((inBufSize > 0) && (inBuffer != (Address)0) &&
  1153.                (inBuffer != (Address)NIL)) {
  1154.     ioctl.inBuffer  = inBuffer;
  1155.     ioctl.inBufSize = inBufSize;
  1156.     } else {
  1157.     ioctl.inBuffer = (Address)NIL;
  1158.     ioctl.inBufSize = 0;
  1159.     }
  1160.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  1161.     if (status == SUCCESS) {
  1162.     /*
  1163.      * Post process the set/get flags stuff because the close-on-exec
  1164.      * flag is not kept down at the stream level, but up along
  1165.      * with the streamID.
  1166.      */
  1167.     fsPtr = procPtr->fsPtr;
  1168.     switch(command) {
  1169.  
  1170.         case IOC_GET_FLAGS: {
  1171.         if (fsPtr->streamFlags[streamID] & FS_CLOSE_ON_EXEC) {
  1172.             *(int *)ioctl.outBuffer |= IOC_CLOSE_ON_EXEC;
  1173.         }
  1174.         break;
  1175.         }
  1176.  
  1177.         case IOC_SET_BITS:
  1178.         case IOC_SET_FLAGS: {
  1179.         int flags;
  1180.         flags = *(int *)ioctl.inBuffer;
  1181.  
  1182.         if (flags & IOC_CLOSE_ON_EXEC) {
  1183.             fsPtr->streamFlags[streamID] |= FS_CLOSE_ON_EXEC;
  1184.         } else if (command == IOC_SET_FLAGS) {
  1185.             fsPtr->streamFlags[streamID] &= ~FS_CLOSE_ON_EXEC;
  1186.         }
  1187.         break;
  1188.         }
  1189.  
  1190.         case IOC_CLEAR_BITS:{
  1191.         int flags;
  1192.         flags = *(int *)ioctl.inBuffer;
  1193.         if (flags & IOC_CLOSE_ON_EXEC) {
  1194.             fsPtr->streamFlags[streamID] &= ~FS_CLOSE_ON_EXEC;
  1195.         }
  1196.         break;
  1197.         }
  1198.     }
  1199.     }
  1200.     return(status);
  1201. }
  1202.  
  1203.  
  1204. /*
  1205.  *----------------------------------------------------------------------
  1206.  *
  1207.  * Fs_SocketStub --
  1208.  *
  1209.  *    The stub for the "socket" Unix system call.
  1210.  *
  1211.  * Results:
  1212.  *    Returns -1 on failure.
  1213.  *
  1214.  * Side effects:
  1215.  *    Side effects associated with the system call.
  1216.  *     
  1217.  *
  1218.  *----------------------------------------------------------------------
  1219.  */
  1220. int
  1221. Fs_SocketStub(domain, type, protocol)
  1222.     int domain;         /* Type of communications domain */
  1223.     int type;           /* Type of socket: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW. */
  1224.     int protocol;       /* Specific protocol to use. */
  1225. {
  1226.     int                status = 0;
  1227.     int                 streamID;
  1228.     int            err;
  1229.     Fs_IOReply          reply;
  1230.  
  1231.     if (debugFsStubs) {
  1232.     printf("Fs_SocketStub(%d, %d, %d)\n",domain, type, protocol);
  1233.     }
  1234.     if (domain != PF_INET) {
  1235.     Mach_SetErrno(EINVAL);
  1236.     return -1;
  1237.     }
  1238.  
  1239.     if (!gotHostName) {
  1240.     if (!strcmp(sys_HostName, "unknown")) {
  1241.         printf("*** host name uninitialized\n");
  1242.     } else {
  1243.         gotHostName = TRUE;
  1244.     }
  1245.         (void) sprintf(streamDevice, INET_STREAM_NAME_FORMAT, sys_HostName);
  1246.         (void) sprintf(dgramDevice, INET_DGRAM_NAME_FORMAT, sys_HostName);
  1247.         (void) sprintf(rawDevice, INET_RAW_NAME_FORMAT, sys_HostName);
  1248.     }
  1249.  
  1250.     if (type == SOCK_STREAM) {
  1251.         streamID = Fs_NewOpenStubInt(streamDevice, FS_READ|FS_WRITE, 0666);
  1252.     } else if (type == SOCK_DGRAM) {
  1253.         streamID = Fs_NewOpenStubInt(dgramDevice, FS_READ|FS_WRITE, 0666);
  1254.     } else if (type == SOCK_RAW) {
  1255.         streamID = Fs_NewOpenStubInt(rawDevice, FS_READ|FS_WRITE, 0666);
  1256.     } else {
  1257.     Mach_SetErrno(EINVAL);
  1258.         return -1;
  1259.     }
  1260.     if (streamID<0) {
  1261.     printf("Fs_SocketStub: open failure\n");
  1262.     return streamID;
  1263.     }
  1264.  
  1265.     if (protocol != 0) {
  1266.         status = Fs_IoctlInt(streamID, IOC_NET_SET_PROTOCOL,
  1267.         sizeof(int), (Address)&protocol, 0, NULL, &reply, &err);
  1268.     }
  1269.  
  1270.     if (status < 0) {
  1271.     printf("Fs_SocketStub: ioctl failure\n");
  1272.     return -1;
  1273.     }
  1274.     return streamID;
  1275. }
  1276.  
  1277. /*
  1278.  *----------------------------------------------------------------------
  1279.  *
  1280.  * connect --
  1281.  *
  1282.  *    For a stream socket, create a connection to a remote host.
  1283.  *    For a datagram socket, only receive datagrams from this remote 
  1284.  *    address.
  1285.  *
  1286.  * Results:
  1287.  *    If 0        - Successful.
  1288.  *    If UNIX_ERROR, then errno = 
  1289.  *    EINVAL        - Bad size for *namePtr,
  1290.  *    EADDRINUSE    - The address is already in use.
  1291.  *    EADDRNOTAVAIL    - The address is not valid for this host.
  1292.  *    EISCONN        - The socket is already connected.
  1293.  *    ETIMEDOUT    - The connection request timed-out.
  1294.  *    ECONNREFUSED    - The remote host refused the connection.
  1295.  *    ENETUNREACH    - The network isn't reachable from this host.
  1296.  *    EWOULDBLOCK    - If non-blocking, the connection can't be completed
  1297.  *                immediately.
  1298.  *    EFAULT        - Invalid argument to the ioctl.
  1299.  *
  1300.  * Side effects:
  1301.  *    A local address for the socket is given if it did not have one 
  1302.  *    already.
  1303.  *
  1304.  *----------------------------------------------------------------------
  1305.  */
  1306.  
  1307. int
  1308. Fs_ConnectStub(socketID, namePtr, nameLen)
  1309.     int            socketID;    /* Stream ID of socket. */
  1310.     struct sockaddr    *namePtr;    /* Remote address,port to connect to.*/
  1311.     int            nameLen;    /* Size of *namePtr. */
  1312. {
  1313.     ReturnStatus    status;
  1314.  
  1315.     if (nameLen != sizeof(struct sockaddr_in)) {
  1316.     return(SYS_INVALID_ARG);
  1317.     }
  1318.  
  1319.     status = Fs_IOControlStub(socketID, IOC_NET_CONNECT,
  1320.                   nameLen, (Address) namePtr, 
  1321.                   0, (Address) NULL);
  1322.  
  1323.     if (status == FS_WOULD_BLOCK) {
  1324.     int flags = 0;
  1325.     Address    usp;
  1326.     int *intPtr;
  1327.     int optionsArray[2];
  1328.     int *userOptionsArray;
  1329.  
  1330.     usp = (Address)Mach_UserStack();
  1331.     intPtr = (int *)(usp - sizeof(int));
  1332.     userOptionsArray = 
  1333.             (int *)(Mach_UserStack() - 3 * sizeof(int));
  1334.  
  1335.     /*
  1336.      * The connection didn't immediately complete, so wait if
  1337.      * we're blocking or return EWOULDBLOCK if we're non-blocking.
  1338.      */
  1339.     status = Fs_IOControlStub(socketID, IOC_GET_FLAGS, 
  1340.             0, (Address) NULL,
  1341.             sizeof(flags), (Address) intPtr);
  1342.  
  1343.     if (status != SUCCESS) {
  1344.         DebugMsg(status, "connect (ioctl)");
  1345.         UNIXRETURN(status);
  1346.     }
  1347.     (void)Vm_CopyIn(sizeof(flags), (Address)intPtr, (Address)&flags);
  1348.  
  1349.     if (flags & IOC_NON_BLOCKING) {
  1350.         UNIXRETURN(FS_WOULD_BLOCK);
  1351.     } 
  1352.  
  1353.     status = Wait(socketID, FALSE, &time_OneMinute);
  1354.  
  1355.     if (status == FS_TIMEOUT) {
  1356.         DebugMsg(status, "connect (select)");
  1357.         UNIXRETURN(status);
  1358.     }
  1359.  
  1360.     /*
  1361.      * See if the connection successfully completed.
  1362.      */
  1363.     optionsArray[0] = SOL_SOCKET;
  1364.     optionsArray[1] = SO_ERROR;
  1365.     status = Vm_CopyOut(2 * sizeof(int), (Address)optionsArray, 
  1366.                 (Address)userOptionsArray);
  1367.     if (status != SUCCESS) {
  1368.         UNIXRETURN(status);
  1369.     }
  1370.     status = Fs_IOControlStub(socketID, IOC_NET_GET_OPTION,
  1371.             sizeof(optionsArray), (Address) userOptionsArray, 
  1372.             sizeof(int), (Address) intPtr);
  1373.     if (status != SUCCESS) {
  1374.         DebugMsg(status, "connect (getsockopt)");
  1375.         UNIXRETURN(status);
  1376.     }
  1377.     (void)Vm_CopyIn(sizeof(int), (Address)intPtr, (Address)&status);
  1378.     } else if (status != SUCCESS) {
  1379.     DebugMsg(status, "connect");
  1380.     }
  1381.     UNIXRETURN(status);
  1382. }
  1383.  
  1384. /*ARGSUSED*/
  1385. /*
  1386.  *----------------------------------------------------------------------
  1387.  *
  1388.  * Fs_SocketpairStub --
  1389.  *
  1390.  *      The stub for the "socketpair" Unix system call.
  1391.  *
  1392.  * Results:
  1393.  *      Returns -1 on failure.
  1394.  *
  1395.  * Side effects:
  1396.  *      Side effects associated with the system call.
  1397.  *     
  1398.  *
  1399.  *----------------------------------------------------------------------
  1400.  */
  1401. int
  1402. Fs_SocketpairStub(d, type, protocol, sv)
  1403.     int d, type, protocol;
  1404.     int sv[2];
  1405. {
  1406.     printf("socketpair is not implemented\n");
  1407.     Mach_SetErrno(EINVAL);
  1408.     return -1;
  1409. }
  1410.  
  1411. /*
  1412.  *----------------------------------------------------------------------
  1413.  *
  1414.  * Wait --
  1415.  *
  1416.  *    Wait for the Inet server to indicate that a socket is ready
  1417.  *    for some action.
  1418.  *
  1419.  * Results:
  1420.  *    SUCCESS, or FS_TIMEOUT if a timeout occurred.
  1421.  *
  1422.  * Side effects:
  1423.  *    None.
  1424.  *
  1425.  *----------------------------------------------------------------------
  1426.  */
  1427.  
  1428. static ReturnStatus
  1429. Wait(socketID, readSelect, timeOutPtr)
  1430.     int     socketID;    /* Socket to wait on. */
  1431.     Boolean    readSelect;    /* If TRUE, select for reading, else select for
  1432.                  *  writing. */
  1433.     Time    *timeOutPtr;    /* Timeout to use for select. */
  1434. {
  1435.     ReturnStatus    status;
  1436.     int            numReady;
  1437.     Address        usp;
  1438.     int            *numReadyPtr;
  1439.     int            *userMaskPtr;
  1440.     Time        *userTimeOutPtr;
  1441.  
  1442.     if (debugFsStubs) {
  1443.     printf("Wait(%d, %d, %x)\n", socketID, readSelect, timeOutPtr);
  1444.     }
  1445.     usp = Mach_UserStack();
  1446.     usp -= sizeof(int);
  1447.     numReadyPtr = (int *)usp;
  1448.  
  1449.     if (timeOutPtr == (Time *)NULL) {
  1450.     userTimeOutPtr = (Time *)NULL;
  1451.     } else {
  1452.     usp -= sizeof(Time);
  1453.     userTimeOutPtr = (Time *)usp;
  1454.     status = Vm_CopyOut(sizeof(Time), (Address)timeOutPtr, 
  1455.                 (Address)userTimeOutPtr);
  1456.     if (status != SUCCESS) {
  1457.         return(status);
  1458.     }
  1459.     }
  1460.     /*
  1461.      * Wait until the Inet server indicates the socket is ready.
  1462.      */
  1463.  
  1464.     if (socketID < 32) {
  1465.     int    mask;
  1466.  
  1467.     usp -= sizeof(int);
  1468.     userMaskPtr = (int *)usp;
  1469.     mask = 1 << socketID;
  1470.     status = Vm_CopyOut(sizeof(int), (Address)&mask, (Address)userMaskPtr);
  1471.     if (status != SUCCESS) {
  1472.         return(status);
  1473.     }
  1474.     if (readSelect) {
  1475.         status = Fs_SelectStub(socketID+1, userTimeOutPtr, userMaskPtr,
  1476.                 (int *) NULL, (int *) NULL, numReadyPtr);
  1477.     } else {
  1478.         status = Fs_SelectStub(socketID+1, userTimeOutPtr, (int *) NULL, 
  1479.                 userMaskPtr, (int *) NULL, numReadyPtr);
  1480.     }
  1481.     } else {
  1482.     int    *maskPtr;
  1483.     int    numBytes;
  1484.  
  1485.     Bit_Alloc(socketID, maskPtr);
  1486.     Bit_Set(socketID, maskPtr);
  1487.     numBytes = Bit_NumBytes(socketID);
  1488.     usp -= numBytes;
  1489.     userMaskPtr = (int *)usp;
  1490.     status = Vm_CopyOut(numBytes, (Address)maskPtr, (Address)userMaskPtr);
  1491.     if (status != SUCCESS) {
  1492.         return(status);
  1493.     }
  1494.  
  1495.     if (readSelect) {
  1496.         status = Fs_SelectStub(socketID+1, userTimeOutPtr, userMaskPtr, 
  1497.                 (int *) NULL, (int *) NULL, numReadyPtr);
  1498.     } else {
  1499.         status = Fs_SelectStub(socketID+1, userTimeOutPtr, (int *) NULL,
  1500.                 userMaskPtr, (int *) NULL, numReadyPtr);
  1501.     }
  1502.     free((char *) maskPtr);
  1503.     }
  1504.  
  1505.     if (status == FS_TIMEOUT) {
  1506.     return(status);
  1507.     } else if (status != SUCCESS) {
  1508.     DebugMsg(status, "Wait (socket.c): Fs_Select failed.\n");
  1509.     }
  1510.  
  1511.     (void)Vm_CopyIn(sizeof(int), (Address)numReadyPtr, (Address)&numReady);
  1512.     if (numReady != 1) {
  1513.     DebugMsg(numReady, "Wait (socket.c): Fs_Select numReady != 1\n");
  1514.     }
  1515.  
  1516.     return(SUCCESS);
  1517. }
  1518.